package designPatterns_demo.lambda_demo;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamDemo {

    public static void main(String[] args) {
        //forEach()
        // 使用Stream.forEach()迭代
        Stream<String> stream = Stream.of("I", "love", "you", "too");
        stream.forEach(str -> System.out.println(str));
        System.out.println("******************************************************************");
        // filter()
        // 使用filter()方法保留长度等于3的字符串
        stream = Stream.of("I", "love", "you", "too");
        stream.filter(str -> str.length() > 3).forEach(str -> System.out.println(str));
        System.out.println("******************************************************************");
        // distinct()
        // 函数原型为Stream<T> distinct()，作用是返回一个去除重复元素之后的Stream。
        stream= Stream.of("I", "love", "you", "too", "too");
        stream.distinct().forEach(str -> System.out.println(str));
        System.out.println("******************************************************************");
        // sorted()
        // 排序函数有两个，一个是用自然顺序排序，一个是使用自定义比较器排序，函数原型分别为Stream<T>　sorted()和Stream<T>　sorted(Comparator<? super T> comparator)。
        stream = Stream.of("I", "love", "you", "too");
        stream.sorted((str1, str2) -> str1.length() - str2.length()).forEach(str -> System.out.println(str));
        System.out.println("******************************************************************");
        // map()
        // 函数原型为<R> Stream<R> map(Function<? super T,? extends R> mapper)，作用是返回一个对当前所有元素执行执行mapper之后的结果组成的Stream。直观的说，就是对每个元素按照某种操作进行转换，转换前后Stream中元素的个数不会改变，但元素的类型取决于转换之后的类型。
        stream = Stream.of("I", "love", "you", "too");
        stream.map(str -> str.toUpperCase()).forEach(str -> System.out.println(str));
        System.out.println("******************************************************************");
        // flatMap()
        // 函数原型为<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)，作用是对每个元素执行mapper指定的操作，并用所有mapper返回的Stream中的元素组成一个新的Stream作为最终返回结果。说起来太拗口，通俗的讲flatMap()的作用就相当于把原stream中的所有元素都"摊平"之后组成的Stream，转换前后元素的个数和类型都可能会改变。
        Stream<List<Integer>> stream1 = Stream.of(Arrays.asList(1,2,8,0,99), Arrays.asList(3, 4, 5, 78, 34, 57));
        stream1.flatMap(list -> list.stream()).sorted()
                .forEach(i -> System.out.println(i));
        System.out.println("******************************************************************");
        // 多面手reduce()
        // 需求：从一组单词中找出最长的单词。这里“大”的含义就是“长”。
        stream = Stream.of("I", "love", "you", "too");
        // 找出最长的单词
        Optional<String> longest = stream.reduce((s1, s2) -> s1.length()>=s2.length() ? s1 : s2);
        //Optional<String> longest = stream.max((s1, s2) -> s1.length()-s2.length());
        System.out.println(longest.get());
        System.out.println("******************************************************************");
        // 需求：求出一组单词的长度之和。这是个“求和”操作，操作对象输入类型是String，而结果类型是Integer。
        stream = Stream.of("I", "love", "you", "too");
        // 求单词长度之和
        Integer lengthSum = stream.reduce(0, // 初始值　// (1)
                (sum, str) -> sum + str.length(), // 累加器 // (2)
                (a,b) -> a + b); // 部分和拼接器，并行执行时才会用到 // (3)
        System.out.println(lengthSum);
        // 使用map()和sum()组合
        stream = Stream.of("I", "love", "you", "too");
        int lengthSum1 = stream.mapToInt(str -> str.length()).sum();
        System.out.println(lengthSum1);
        System.out.println("******************************************************************");
        // >>> 终极武器collect() <<<
        // 将Stream转换成容器或Map
        stream = Stream.of("I", "love", "you", "too");
        List<String> list = stream.collect(Collectors.toList());
        // Set<String> set = stream.collect(Collectors.toSet());
        // 1.接口的静态方法和默认方法 // ava 8允许在接口中加入具体方法。接口中的具体方法有两种，default方法和static方法，identity()就是Function接口的一个静态方法。 Function.identity()返回一个输出跟输入一样的Lambda表达式对象，等价于形如t -> t形式的Lambda表达式。
        // 2.方法引用 // 诸如String::length的语法形式叫做方法引用（method references），这种语法用来替代某些特定形式Lambda表达式。如果Lambda表达式的全部内容就是调用一个已有的方法，那么可以用方法引用来替代Lambda表达式。
        // Map<String, Integer> map = stream.collect(Collectors.toMap(Function.identity(), String::length));
        System.out.println("******************************************************************");
        stream = Stream.of("I", "love", "you", "too");
        //　将Stream规约成List
        List<String> list1 = stream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll); // 方式1
        // List<String> list1 = stream.collect(Collectors.toList()); // 方式2
        System.out.println("******************************************************************");
        stream = Stream.of("I", "love", "you", "too");
        // // 使用toCollection()指定规约容器的类型
        ArrayList<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
        // HashSet<String> set2 = stream.collect(Collectors.toCollection(HashSet::new));

        System.out.println("******************************************************************");

        List<Integer> lists = new ArrayList<>();
        lists.add(1);
        lists.add(2);
        lists.add(3);

        Integer product = lists.parallelStream().reduce(1, (a, b) -> a *  (b * 2),
                (a, b) -> a * b * 2 );
        System.out.println("product=============:" + product);//192

        System.out.println("******************************************************************");

        //(广州  深圳  上海  北京)的全拼的一些组合,下面我们就把每一个城市都划分一下
        List<String> citys = Arrays.asList("GuangZhou ShangHai", "GuangZhou ShenZhen",
                "ShangHai ShenZhen", "BeiJing ShangHai", "GuangZhou BeiJing", "ShenZhen BeiJing");

        //这里打印的数组对应的地址
        citys.stream().map(mCitys -> Arrays.stream(mCitys.split(" "))).forEach(System.out::println);//note1

        System.out.println("note1note1note1note1note1note1note1note1note1note1");

        //流里面的元素还是一个数组
        citys.stream()
                .map(mCities -> Arrays.stream(mCities.split(" ")))//流里面的每个元素还是数组
                .forEach(cities ->cities.forEach(city-> System.out.println(city+" ")));//note2

        System.out.println("note2note2note2note2note2note2note2note2note2note2");

        //直接一个flatMap()就把数组合并到映射流里面了
        citys.stream().flatMap(mCities->Arrays.stream(mCities.split(" "))).forEach(System.out::println);//note3

        System.out.println("note3note3note3note3note3note3note3note3note3note3");

        //使用distinct()方法去重！
        citys.stream().flatMap(mCities->Arrays.stream(mCities.split(" "))).distinct().forEach(System.out::println);//note4

        System.out.println("note4note4note4note4note4note4note4note4note4note4");

        List<String> listss = Arrays.asList("A", "B", "C", "D");
        listss.stream().spliterator().forEachRemaining(System.out::println);
    }

}
